#include "FServer/FServer.h"

#include <memory>

namespace keeper_server {


int FServer::main(const std::vector<std::string> & /*args*/) {
  std::string listen_host = "127.0.0.1";
  unsigned int port = 1234;
  Poco::ThreadPool server_pool(3, 1024);

  Poco::Net::ServerSocket socket;
  auto address = socketBindListen(socket, listen_host, port);
  socket.setReceiveTimeout(1);
  socket.setSendTimeout(1);
  auto fserver = std::make_unique<Poco::Net::TCPServer>(
      new MySQLTCPHandlerFactory(), server_pool, socket,
      new Poco::Net::TCPServerParams);
  fserver->start();
  LOG_INFO("Listening for connections to Keeper (tcp): %s",
           address.toString().c_str());
  waitForTerminationRequest();
  LOG_INFO("Stop listen %s", address.toString().c_str());
  fserver->stop();

  return 0;
}


Poco::Net::SocketAddress makeSocketAddress(const std::string& host,
                                           unsigned int port) {
  Poco::Net::SocketAddress socket_address;
  try {
    socket_address = Poco::Net::SocketAddress(host, port);
  } catch (const Poco::Net::DNSException& e) {
    throw;
  }
  return socket_address;
}

Poco::Net::SocketAddress FServer::socketBindListen(
    Poco::Net::ServerSocket& socket, const std::string& host, unsigned port,
    bool secure) const {
  auto address = makeSocketAddress(host, port);
#if !defined(POCO_CLICKHOUSE_PATCH) || POCO_VERSION < 0x01090100
  if (secure)
    /// Bug in old (<1.9.1) poco, listen() after bind() with reusePort param
    /// will fail because have no implementation in SecureServerSocketImpl
    /// https://github.com/pocoproject/poco/pull/2257
    socket.bind(address, /* reuseAddress = */ true);
  else
#endif
#if POCO_VERSION < 0x01080000
    socket.bind(address, /* reuseAddress = */ true);
#else
  socket.bind(address, /* reuseAddress = */ true,
              /* reusePort = */ config().getBool("listen_reuse_port", false));
#endif

  socket.listen(/* backlog = */ config().getUInt("listen_backlog", 64));

  return address;
}

}  // namespace keeper_server
